chore: take over release automation and remove Stainless dependencies#100
Conversation
Stainless (acquired by Anthropic) sunsets its platform for our account on 2026-09-01. This implements Problem 1 of the attached design doc: - Add self-hosted release-please workflow (replaces the Stainless app, which opened release PRs and created tags/GitHub Releases externally) - Point release-please-config.json $schema at upstream googleapis - Simplify CI triggers to main + PRs; drop stainless-sdks runner conditionals and the pkg.stainless.com artifact upload - Remove .stats.yml (Stainless codegen metadata) - Rewrite CONTRIBUTING.md and SECURITY.md for owned, hand-maintained code - Drop "generated with Stainless" phrasing and the vscode.stainless.com MCP badge from README - Add the approved design doc (docs/design/stainless-exit-and-v2.md) Co-Authored-By: Claude Fable 5 <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR transitions release orchestration from the external Stainless GitHub App to in-repo GitHub Actions, and removes remaining Stainless-specific metadata and CI steps so releases/publishing continue to work after the Stainless sunset.
Changes:
- Added a self-hosted
release-pleaseworkflow on pushes tomain, using the existing manifest/config. - Simplified CI triggers and removed Stainless-only runner/artifact-upload logic.
- Cleaned up documentation and removed Stainless metadata/files (
.stats.yml, artifact upload script, README/SECURITY/CONTRIBUTING updates) plus added the design doc.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
SECURITY.md |
Updates vulnerability reporting guidance away from Stainless to GitHub reporting + LandingAI support. |
scripts/utils/upload-artifact.sh |
Removes Stainless storage artifact upload script. |
release-please-config.json |
Points schema to the upstream googleapis release-please schema URL. |
README.md |
Removes “generated with Stainless” wording and the VS Code Stainless MCP badge. |
docs/design/stainless-exit-and-v2.md |
Adds the approved design doc describing the Stainless exit and future pipeline direction. |
CONTRIBUTING.md |
Updates contribution guidance to reflect hand-maintained ownership and Conventional Commits for release automation. |
.stats.yml |
Removes Stainless codegen metadata file. |
.github/workflows/release-please.yml |
Adds self-hosted release-please workflow using a repo secret token. |
.github/workflows/ci.yml |
Simplifies triggers/runners and removes Stainless-only conditionals and artifact upload steps. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Per review: ordinary merges to main must never create release PRs. Releases now start with a maintainer running the Release workflow and choosing patch/minor/major; the release-please CLI opens a release PR pinned to exactly that version (changelog and version stamping still come from the existing config/manifest). Merging that PR triggers the finalize job, which creates the tag + GitHub Release and thereby the PyPI publish. Config drops the now-bypassed prerelease versioning keys. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Release model revised per Mingrui's feedback: releases are now dispatch-only — a maintainer runs the Release workflow and explicitly picks patch/minor/major; ordinary merges to main never open release PRs. See the updated |
Per review: dispatching the Release workflow IS the release decision, so the intermediate release PR is gone. The workflow now stamps the version (pyproject.toml, _version.py), prepends the changelog section, lands the release commit directly on main (requires the RELEASE_TOKEN owner to have ruleset bypass), tags it, and creates the GitHub Release that triggers the PyPI publish. release-please is fully removed (config, manifest, version annotations) in favor of a small owned script. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Revised again per feedback: the release PR is gone entirely. Dispatching Release (with an explicit patch/minor/major choice) now stamps versions + changelog, lands the release commit directly on main via ruleset bypass, tags, and publishes — one human action total. release-please is fully removed in favor of a small owned script (smoke-tested against the real commit history). Note the secret is now named |
Length-sorted imports with future annotations (isort length-sort + FA102), typed the bucket dict for strict pyright, and replaced print with sys.stdout.write (T201). Verified locally against the pinned ruff 0.14.13, pyright 1.1.399, and mypy 1.17.0. Co-Authored-By: Claude Fable 5 <[email protected]>
- Add a concurrency group to the Release workflow so concurrent dispatches queue instead of racing the version computation - Hoist SECTION_KEYS out of the per-commit loop in the notes script - Drop the Stainless-generated header from _version.py - Simplify release-doctor to dispatch-only (its PR trigger gated on release-please branch names that no longer exist) Co-Authored-By: Claude Fable 5 <[email protected]>
Per review: the one-shot release could previously tag and publish without validating the release commit itself. The workflow now runs bootstrap + rye build + tests on the stamped tree and aborts — before any commit, tag, or Release exists — if anything is red. Co-Authored-By: Claude Fable 5 <[email protected]>
|
The header sweep promised in the review is up: #101 (and landing-ai/ade-typescript#71 for the TS side), stacked on this branch — they'll retarget to main when this merges. |
…#70) * fix: configure npm OIDC Trusted Publishing correctly The previous approach installed [email protected] in a ../oidc/ prefix directory and ran it directly, which didn't properly trigger the OIDC token exchange for Trusted Publishing authentication. Changes: - Upgrade setup-node to v4 with registry-url to configure .npmrc - Install [email protected] globally instead of in a prefix directory - Add --provenance and --access public flags to trigger OIDC auth Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * build: fetch tsc-multi from npm instead of the Stainless-hosted tarball package.json pinned tsc-multi to a tarball on the stainless-api GitHub org's release assets, which goes away when that org is archived after the Stainless sunset (2026-09-01). @stainless-api/tsc-multi is published on npm (persists regardless); the bin name is unchanged, so scripts/build works as before. Verified: full root + mcp-server build, pack, and sign pass with 1.1.12. Co-Authored-By: Claude Fable 5 <[email protected]> * chore: take over release automation and remove Stainless dependencies Stainless sunsets its platform for our account on 2026-09-01. This implements Problem 1 of the design doc (landing-ai/ade-python#100): - Add self-hosted release-please workflow (replaces the Stainless app, which opened release PRs and created tags/GitHub Releases externally) - Point release-please-config.json $schema at upstream googleapis and drop the README.md / mcp yarn.lock extra-files (no version strings in either; upstream's generic updater would no-op on them) - Simplify CI triggers to main + PRs; drop stainless-sdks runner conditionals and both pkg.stainless.com artifact uploads - Bump deprecated actions/setup-node (Node 20 action runtimes leave GitHub runners 2026-09-16) - Guard the DXT release-asset upload so manual workflow_dispatch runs don't fail on an empty release tag - Remove .stats.yml and scripts/utils/upload-artifact.sh - Rewrite CONTRIBUTING.md and SECURITY.md for owned, hand-maintained code - Drop "generated with Stainless" phrasing and the vscode.stainless.com MCP badge from README Co-Authored-By: Claude Fable 5 <[email protected]> * chore: trigger CI * chore: make releases dispatch-only with maintainer-chosen version bump Per review: ordinary merges to main must never create release PRs. Releases now start with a maintainer running the Release workflow and choosing patch/minor/major; the release-please CLI opens a release PR pinned to exactly that version (changelog and multi-file version stamping still come from the existing config/manifest). Merging that PR triggers the finalize job, which creates the tag + GitHub Release and thereby the npm publish. Config drops the now-bypassed prerelease versioning keys. Co-Authored-By: Claude Fable 5 <[email protected]> * chore: release directly from dispatch — no release PR Per review: dispatching the Release workflow IS the release decision, so the intermediate release PR is gone. The workflow now stamps the version (package.json, src/version.ts, mcp-server package.json + manifest.json), prepends the changelog section, lands the release commit directly on main (requires the RELEASE_TOKEN owner to have ruleset bypass), tags it, and creates the GitHub Release that triggers the npm publish. release-please is fully removed (config, manifest, version annotations) in favor of a small owned script. Co-Authored-By: Claude Fable 5 <[email protected]> * chore: sync release-notes script lint fixes from ade-python Keep the shared script byte-identical across both SDK repos. Co-Authored-By: Claude Fable 5 <[email protected]> * fix: address Copilot review — release concurrency + cleanups - Add a concurrency group to the Release workflow so concurrent dispatches queue instead of racing the version computation - Sync the notes-script SECTION_KEYS hoist from ade-python - Simplify release-doctor to dispatch-only (its PR trigger gated on release-please branch names that no longer exist) Co-Authored-By: Claude Fable 5 <[email protected]> * fix: gate the release on building and testing the stamped tree Mirror of the ade-python change: bootstrap + build + tests run on the stamped tree, aborting the release before any commit or tag exists if anything is red. Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
The SDK is hand-maintained since the Stainless exit (#100); the "File generated from our OpenAPI spec by Stainless" headers gave contributors guidance that contradicts CONTRIBUTING.md. Mechanical sweep of 34 source files plus the two .keep placeholders. Co-Authored-By: Claude Fable 5 <[email protected]>
The SDK is hand-maintained since the Stainless exit (#100); the "File generated from our OpenAPI spec by Stainless" headers gave contributors guidance that contradicts CONTRIBUTING.md. Mechanical sweep of 34 source files plus the two .keep placeholders. Co-authored-by: Claude Fable 5 <[email protected]>
Context
Stainless sunsets its platform for our account on 2026-09-01. This PR implements Problem 1 (Getting off Stainless) of the design doc — included here as
docs/design/stainless-exit-and-v2.md, status Approved.Today's release pipeline is split: the Stainless GitHub App runs release-please externally (opens release PRs, creates tags + GitHub Releases — every recent release was authored by
stainless-app[bot]), while the in-repopublish-pypi.ymlalready publishes on the release event with our own token. Only the orchestration half dies with the sunset; this PR replaces it.Changes
.github/workflows/release.yml— one-shot, dispatch-only releases. A maintainer runs the workflow and picks patch / minor / major. The workflow computes the next version from the latest tag, stampspyproject.toml+_version.py, prepends the changelog section (generated by the new.github/scripts/generate_release_notes.py, grouped by Conventional Commit prefixes in the existing CHANGELOG style), lands therelease: x.y.zcommit directly onmain, tags it, and creates the GitHub Release →publish-pypi.yml→ PyPI. No release PR; dispatching is the release decision. Ordinary merges never trigger any of this.x-release-please-versionannotation are gone; changelog + stamping are ~70 lines of owned script.ci.yml— triggers simplified tomain+ PRs; removedstainless-sdks/*depot-runner conditionals, thepkg.stainless.comartifact upload, and the codegen-metadata skip..stats.ymlandscripts/utils/upload-artifact.sh.vscode.stainless.combadge.Required before this works end-to-end
RELEASE_TOKENrepo secret — fine-grained PAT (or GitHub App token) with Contents: write, whose owner can bypass the main ruleset (main requires PRs; this repo's ruleset grants "always" bypass to organization admins — the release commit uses that bypass). The defaultGITHUB_TOKENcan't be used: releases it creates don't triggerpublish-pypi.yml.🤖 Generated with Claude Code